using Mapster;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.IdentityModel.Tokens;
using Quartz;
using SmartAgricultureService.Core;
using SmartAgricultureService.Core.Mqtt;
using SmartAgricultureService.Jobs;
using SmartAgricultureService.Models;
using System.Text;
using System.Text.Json.Serialization;

namespace SmartAgricultureService
{
    public class Program
    {
        private static readonly CancellationTokenSource cancellationToken = new CancellationTokenSource();
        public static CancellationTokenSource CancellationTokenSource => cancellationToken;
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            builder.Services.AddOptions();
            builder.Services.AddControllers();
            builder.Services.AddCors(options => options.AddPolicy("cors", policy => policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()));
            AppConfiguration.InitConfiguration(builder.Configuration);
            TypeAdapterConfig.GlobalSettings.AllowImplicitDestinationInheritance = true;
            builder.Services.AddDbContext<DatabaseContext>(opt =>
            {
                var serverVersion = ServerVersion.AutoDetect(AppConfiguration.ConnectionString);
                opt.UseMySql(AppConfiguration.ConnectionString, serverVersion);
            });
            builder.Services.AddHostedService<MqttHostService>();
            builder.Services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
            builder.Services.AddQuartz(options =>
            {
                var createKey = new JobKey(nameof(CreateJob));
                options.AddJob<CreateJob>(opts => opts.WithIdentity(createKey));
                options.AddTrigger(opts => opts.ForJob(createKey).WithIdentity($"{nameof(CreateJob)}-trigger").WithCronSchedule("0 0 2 * * ?"));
                var clearKey = new JobKey(nameof(ClearJob));
                options.AddJob<ClearJob>(opts => opts.WithIdentity(clearKey));
                options.AddTrigger(opts => opts.ForJob(clearKey).WithIdentity($"{nameof(ClearJob)}-trigger").WithCronSchedule("0 0 3 * * ?"));
            });
            builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidIssuer = AppConfiguration.Jwt.Issuer,
                    ValidAudience = AppConfiguration.Jwt.Audience,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AppConfiguration.Jwt.SecretKey))
                };
            });
            builder.Services.AddControllers().AddJsonOptions(options =>
                options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull);
            builder.Services.AddSingleton<JobRunner>();
            builder.Services.AddSingleton<JwtContext>();
            builder.Services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            Utils.Services = builder.Services;
            var app = builder.Build();
            Task.Run(async () =>
            {
                await Task.Delay(3000);
                app.Services.GetService<MqttHostService>();
            });
            app.UseHttpsRedirection();
            app.UseAuthorization();
            app.UseCors("cors");
            app.UseStaticFiles(new StaticFileOptions { RequestPath = "/webs" });
            app.MapControllers();
            app.Run();
        }
    }
}